\section{Keys and rodents}
\label{sec:bindings}

In the stock configuration file setup, most key and mouse bindings are set
from the file \file{cfg\_ioncore.lua} while module-specific bindings
are set from the modules' main configuration files (\file{cfg\_modname.lua}).
This, however, does not have to be so as long as the module has been
loaded prior to defining any module-specific bindings.

Bindings are defined by calling the function 
\fnrefx{ioncore}{defbindings} with the ``context'' of the
bindings and the a table of new bindings to make. The context is simply
string indicating one of the classes of regions (or modes such as
\type{WMoveresMode}) introduced in section \ref{sec:objects}, and fully
listed in appendix \ref{app:fullhierarchy}, although not all define
a binding map. For example, the following skeleton would be used to 
define new bindings for all frames:

\begin{verbatim}
defbindings("WFrame", {
    -- List of bindings to make goes here.
})
\end{verbatim}

There has been some confusion among users about the need to define the
``context'' for each binding, so let me try to explain this design
decision here. The thing is that if there was a just a simple 'bind this 
key to this action' method without knowledge of the context, some 
limitations would have to be made on the available actions and writing 
custom handlers would be more complicated. In addition one may want to 
bind the same function to different key for different types of objects.
Indeed, the workspace and frame tab switching functions are the same both
classes being based on \type{WMPlex}, and in the stock configuration the 
switch to $n$:th workspaces is bound to \key{Mod1+n} while the switch to 
$n$:th tab is bound to the sequence \key{Mod1+k n}.

Currently known contexts include: 
\codestr{WScreen},
\codestr{WMPlex},
\codestr{WMPlex.toplevel},
\codestr{WFrame},
\codestr{WFrame.toplevel},
\codestr{WFrame.floating},
\codestr{WFrame.tiled},
\codestr{WFrame.transient},
\codestr{WMoveresMode},
\codestr{WGroup},
\codestr{WGroupCW},
\codestr{WGroupWS},
\codestr{WClientWin},
\codestr{WTiling}, and
\codestr{WStatusBar}.
Most of these should be self-explanatory, corresponding to objects
of class with the same name. The ones with \codestr{.toplevel} suffix
refer to screens and ``toplevel''  frames, i.e. frames that are
not used for transient windows. Likewise \codestr{.transient} refers
to frames in transient mode, and \codestr{.tiled} and \codestr{.floating}
to frames in, respectively, tiled and floating modes. 

                                                        

The following subsections describe how to construct elements of the
binding table. Note that \fnrefx{ioncore}{defbindings} adds
the the newly defined bindings to the previous bindings of the context,
overriding duplicates. To unbind an event, set the handler parameter
to \code{nil} for each of the functions to be described in the following
subsections.

Also note that when multiple objects want to handle a binding, the 
innermost (when the root window is considered the outermost) active object
in the parent--child hierarchy (see Figure \ref{fig:parentship}) of objects 
gets to handle the action.


\subsection{Binding handlers and special variables}

Unlike in Ion2, in Ion3 binding handlers are not normally passed as
``anonymous functions'', although this is still possible. The preferred
method now is to pass the code of the handler as a string. Two following
special variables are available in this code.

\begin{tabularx}{\linewidth}{lX}
    \tabhead{Variable & Description}
    \code{_} (underscore) &
      Reference to the object on which the 
      binding was triggered. The object is of the same class as the the
      context of the \fnrefx{ioncore}{defbindings} call
      defining the binding. \\
    \code{_sub} &
      Usually, the currently active \emph{managed object} of the 
      object referred to by \code{_}, but sometimes (e.g. mouse actions
      on tabs of frames) something else relevant to the action triggering
      the binding. \\
    \code{_chld} &
      Object corresponding to the currently active child window of the
       object referred to by \code{_}. This should seldom be needed.
\end{tabularx}

For example, supposing \code{_} (underscore) is a \type{WFrame}, the 
following handler should move the active window to the right, if 
possible:

\begin{verbatim}
"_:inc_index(_sub)"
\end{verbatim}

\subsection{Guards}

To suppress error messages, each binding handler may also be accompanied
by a ``guard'' expression that blocks the handler from being called when
the guard condition is not met. Currently the following guard expressions
are supported (for both \code{_sub} and \code{_chld}):

\begin{tabularx}{\linewidth}{lX}
    \tabhead{Guard & Description}
    \codestr{\_sub:non-nil} & The \code{_sub} parameter must be set. \\
    \codestr{\_sub:SomeClass} & The \code{_sub} parameter must be member
      of class \type{SomeClass}. \\
\end{tabularx}


\subsection{Defining the bindings}
\label{sec:binddef}

The descriptions of the individual bindings in the binding table argument
to \fnrefx{ioncore}{defbindings} should be constructed with the following
functions.

Key presses:
\begin{itemize}
    \item \fnrefx{ioncore}{kpress}, and
          \fnrefx{ioncore}{kpress_wait}\code{(keyspec, handler [, guard])}.
    \item \fnrefx{ioncore}{submap}\code{(keyspec, \{ ... more key bindings ... \})}.
    \item \fnrefx{ioncore}{submap_enter}, and
          \fnrefx{ioncore}{submap_wait}\code{(handler [, guard])}.
\end{itemize}
Mouse actions:
\begin{itemize}
    \item \fnrefx{ioncore}{mclick},
          \fnrefx{ioncore}{mdblclick},
          \fnrefx{ioncore}{mpress}, and
          \fnrefx{ioncore}{mdrag}\code{(buttonspec, handler [, guard])}.
\end{itemize}

The actions that most of these functions correspond to should be clear
and as explained in the reference, \fnrefx{ioncore}{kpress_wait} is simply
\fnrefx{ioncore}{kpress} with a flag set instructing Ioncore wait for
all modifiers to be released before processing any further actions.
This is to stop one from accidentally calling e.g.
\fnref{WRegion.rqclose} multiple times in a row. The 
\fnrefx{ioncore}{submap} function is used to define submaps or
``prefix maps''. The second argument to this function is table listing
the key press actions (\fnrefx{ioncore}{kpress}) in the submap. 
The \fnrefx{ioncore}{submap_enter} handler is called when the submap
is entered, in which this handler is defined. Likewise, the
\fnrefx{ioncore}{submap_wait} handler is  called when all modifiers
have been released while waiting for further key presses in the submap.

The parameters \var{keyspec} and \var{buttonspec} are explained below
in detail. The parameter \var{handler} is the handler for the binding,
and the optional parameter \var{guard} its guard. These should normally
be strings as explained above. 

\subsection{Examples}

For example, to just bind the key \key{Mod1+1} to switch to the first
workspace and \key{Mod1+Right} to the next workspace, you would make the
following call
\begin{verbatim}
defbindings("WScreen", {
    kpress("Mod1+Right", "_:switch_next()"),
    kpress("Mod1+1", "_:switch_nth(1)"),
})
\end{verbatim}

Note that \code{_:switch_nth(1)} is the same as calling
\fnref{WMPlex.switch_next}\code{(_, 1)} as \type{WScreen} inherits
\type{WMPlex} and this is where the function is actually defined.

Similarly to the above example, to bind the key sequence \key{Mod1+k n} 
switch to the next managed object within a frame, and \key{Mod1+k 1} to the
first, you would issue the following call:
\begin{verbatim}
defbindings("WFrame", {
    submap("Mod1+K", {
        kpress("Right", "_:switch_next()"),
        kpress("1", "_:switch_nth(1)"),
   }),
})
\end{verbatim}


\subsection{Key specifications}

As seen above, the functions that create key binding specifications require
a \var{keyspec} argument. This argument should be a string containing the
name of a key as listed in the X header file \file{keysymdef.h}%
\footnote{This file can usually be found in the directory
\file{/usr/X11R6/include/X11/}.} without the \code{XK_} prefix.
\index{keysymdef.h@\file{keysymdef.h}}
Most of the key names are quite intuitive while some are not. For example,
the \key{Enter} key on the main part of the keyboard has the less common
name \key{Return} while the one the numpad is called \key{KP\_Enter}.

The \var{keyspec} string may optionally have multiple ``modifier'' names
followed by a plus sign (\code{+}) as a prefix. X defines the following
modifiers:

\key{Shift}, \key{Control}, \key{Mod1} to \key{Mod5},
\key{AnyModifier} and \key{Lock}.
\index{Shift@\key{Shift}}
\index{Control@\key{Control}}
\index{ModN@\key{ModN}}
\index{AnyModifier@\key{AnyModifier}}
\index{Lock@\key{Lock}}

X allows binding all of these modifiers to almost any key and while this
list of modifiers does not explicitly list keys such as 
\key{Alt}\index{Alt@\key{Alt}} that are common on modern keyboards, such
keys are bound to one of the \key{ModN}. On systems running XFree86
\key{Alt} is usually \key{Mod1}. On Suns \key{Mod1} is the diamond key
and \key{Alt} something else. One of the ``flying window'' keys on so
called Windows-keyboards is probably mapped to \key{Mod3} if you have
such a key. Use the program \file{xmodmap}\index{xmodmap@\file{xmodmap}}
to find out what exactly is bound where. 

Ion defaults to \key{AnyModifier} in submaps. This can sometimes lead to
unwanted effects when the same key is used with and without explicitly
specified modifiers in nested regions. For this reason, Ion recognises
\key{NoModifier} as a special modifier that can be used to reset this
default.

Ion ignores the \key{Lock} modifier and any \key{ModN} ($N=1{\ldots} 5$)
bound to \key{NumLock}\index{NumLock@\key{NumLock}} or
\key{ScrollLock}\index{ScrollLock@\key{ScrollLock}}
by default because such\footnote{Completely useless keys that should be
gotten rid of in the author's opinion.} locking keys may otherwise
cause confusion.


\subsection{Button specifications}

Button specifications are similar to key definitions but now
instead of specifying modifiers and a key, you specify modifiers
and one of the button names \key{Button1} to
\key{Button5}\index{Button-n@\key{Button-n}}. Additionally the
specification may end with an optional area name following an @-sign.
Only frames currently support areas, and the supported values in this
case are
\codestr{border}, \codestr{tab}, \codestr{empty\_tab}, \codestr{client} 
and \code{nil} (for the whole frame).

For example, the following code binds dragging a tab with the first 
button pressed to initiate tab drag\&drop handling:

\begin{verbatim}
defbindings("WFrame", {
    mdrag("Button1@tab", "_:p_tabdrag()"),
})
\end{verbatim}


\subsection{A further note on the default binding configuration}

The default binding configuration contains references to the variables
\code{META} and \code{ALTMETA} instead of directly using the default
values of \codestr{Mod1+} and \codestr{} (nothing). As explained in
section \ref{sec:walkthrough}, the definitions of these variables
appear in \file{cfg\_ion.lua}. This way you can easily change the the
modifiers used by all bindings in the default configuration without 
changing the whole binding configuration. Quite a few people prefer 
to use the Windows keys as modifiers because many applications already
use \key{Alt}. Nevertheless, \key{Mod1} is the default as a key bound 
to it is available virtually everywhere.

